<template>
  <div class="content">
    <div class="title">问题分布</div>
    <div class="searchBar">
      <div class="searchItem">
        <span>搜索任务:&nbsp;</span>
        <input
          v-model="taskSelected"
          style="
            height: 35px;
            width: 260px;
            border: 1px solid rgba(224, 224, 230);
            border-radius: 4px;
            box-sizing: border-box;
            padding-left: 10px;
            background-color: #fff;
          "
          placeholder="请输入任务编号或名称"
          input
        >
      </div>
      <div class="searchItem">
        <span>问题类型:&nbsp;</span>
        <n-select
          v-model:value="questionTypeSelected"
          style="margin-right: 26px"
          :options="typeList"
        />
      </div>
      <div class="searchItem">
        <span>问题状态:&nbsp;</span>
        <n-select v-model:value="stateSelected" :options="stateList" />
      </div>
      <div class="btns">
        <button
          class="queryBtn"
          :style="queryStyle"
          @mouseenter="queryEnter()"
          @mouseleave="queryLeave()"
          @click="query"
        >
          查询
        </button>
        <button
          class="resetBtn"
          :style="resetStyle"
          @click="reset"
          @mouseenter="resetEnter()"
          @mouseleave="resetLeave()"
        >
          重置
        </button>
      </div>
    </div>
    <!-- 地图页面 -->
    <div class="mapContent">
      <div id="map" class="map" />

      <div ref="pointPopup" class="pointPopup">
        <div class="item">
          <div class="itemTitle">问题类型&nbsp;:&nbsp;</div>
          {{ problemType }}
        </div>
        <div class="item">
          <div class="itemTitle">经纬度&nbsp;:&nbsp;</div>
          {{ positionShow }}
        </div>
        <div class="item">
          <div class="itemTitle">图片&nbsp;:&nbsp;</div>
          <img
            v-for="(item, index) in imgList"
            :key="index"
            :src="item"
            @click="showImage(item)"
          >
          <span v-if="!hasImg">暂无图片</span>
        </div>
      </div>
      <!-- 聚合弹窗 -->
      <div ref="clusterPopup" class="clusterPopup">
        <div v-for="(item, index) in clusterList" :key="index">
          <div class="item">
            <div class="itemtitle">问题类型:&nbsp;</div>
            <div class="clusterNumber">{{ item.type }}</div>
          </div>
          <div class="item">
            <div class="itemtitle">问题数量:&nbsp;</div>
            <div class="clusterNumber">{{ item.number }}</div>
          </div>
        </div>
      </div>
    </div>
    <!-- 遮罩层 -->

    <div v-if="mockShow" class="mock" @click="mockShow = !mockShow">
      <img v-show="picturePreviewShow" :src="previewPictureSrc">
    </div>
  </div>
</template>

<script>
import mapboxgl from 'mapbox-gl'
import { onMounted, reactive, toRefs, ref, unref, createApp } from 'vue'
import { getTaskInspectionType } from '@/api/task/index'
import { getQuestionDistribution } from '@/api/question/index'
import imagesMap from '@/components/BaseMap/tools/gisImage.js'
export default {
  name: 'QuestionDistribut',
  setup(props, { emit }) {
    const data = reactive({
      map: null,
      task: null,
      taskSelected: null,
      styleSelected: null,
      styleList: null,
      stateSelected: 20,
      stateList: [
        { value: 15, label: '已确认' },
        { value: 20, label: '已生成工单' },
        { value: 25, label: '问题已处理' }
      ],
      questionTypeSelected: null,
      typeList: [],
      colorList: [
        '#F99057',
        '#B5E241',
        '#FBE842',
        '#23C343',
        '#37D4CF',
        '#57A9FB',
        '#4080FF',
        '#8D4EDA',
        '#E13EDB',
        '#F754A8',
        '#a9aeb8'
      ],
      colorStrokeList: [
        'rgba(249,144,87,0.5)',
        'rgba(181,226,65,0.5)',
        'rgba(251,232,66,0.5)',
        'rgba(35,195,67,0.5)',
        'rgba(55,212,207,0.5)',
        'rgba(87,169,251,0.5)',
        'rgba(64,128,255,0.5)',
        'rgba(141,78,218,0.5)',
        'rgba(225,62,219,0.5)',
        'rgba(247,84,168,0.5)',
        'rgba(169,174,184,0.5)'
      ],
      popup: null,
      clusterPopup: null,
      pointPopup: null,
      problemType: null, // 问题类型名称
      position: null, // 位置信息,
      popupShow: false,
      imgList: [],
      hasImg: false,
      problemList: [],
      isCluster: false, // 如果是聚合图层 就不显示经纬度
      positionShow: null,
      popupShowNum: 0,
      mockShow: false,
      picturePreviewShow: false,
      previewPictureSrc: null,
      problemClusterId: null, // 当前所点击的问题聚合点的id
      problemPopupId: null,
      clusterContent: null,
      resetStyle: { border: '1px solid #acb9d1' },
      queryStyle: { backgroundColor: 'rgba(24, 144, 255, 1)' },
      clusterList: [],
      clusterPosition: null, // 聚合图层的经纬度
      pointPoppupContent: null, // 点图层弹窗
      pointId: null// 当前所点击的点id
      // 当前点击处的弹窗id
    })
    const initMap = () => {
      mapboxgl.accessToken =
        'pk.eyJ1IjoiNDMyMzQyMjIyMiIsImEiOiJjbDhtcW5qcGkwNWVnM3ZwYnYyNWV2MDJ6In0.Rd7TsRZfKQtke3KT1JduXQ'
      data.map = new mapboxgl.Map({
        container: 'map',
        style: {
          // 设置版本号，一定要设置
          version: 8,

          // 添加来源
          sources: {
            tdtVec: {
              type: 'raster',
              tiles: [
                'https://t0.tianditu.gov.cn/vec_w/wmts?tk=f634525a82da65f715d168d7ba1899c0&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles'
              ],
              tileSize: 256,
              maxZoom: 17
            }
          },
          layers: [
            {
              // 图层id，要保证唯一性
              id: 'tdtVec',
              // 图层类型
              type: 'raster',
              // 数据源
              source: 'tdtVec',
              // 图层最小缩放级数
              minzoom: 0,
              // 图层最大缩放级数
              maxZoom: 17
            }
          ],
          glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
          sprite: 'mapbox://sprites/mapbox/bright-v8'
        },
        center: [118.76, 32.06],
        zoom: 7,
        maxPitch: 0,
        maxZoom: 17,
        dragRotate: false,
        renderWorldCopies: false
      })
      data.map.on('load', () => {
        data.map.loadImage(imagesMap['wenti'], (error, image) => {
          if (error) throw error
          data.map.addImage('problem', image)
        })
      })
      // 单击聚合图层出现的弹窗
      data.map.on('click', 'plantCluster', showClusterInfo)

      // 单击具体点出现的弹窗
      data.map.on('click', 'plant-point', showPlantPointInfo)
    }
    /**
     * 获取问题类型
     */
    const getQuestionType = async function() {
      const { data } = await getTaskInspectionType()
      getQuestionTypeList(data)
    }
    const getQuestionTypeList = (newArr) => {
      const arr = []
      newArr.map((item) => {
        const obj = {}
        obj.value = item.code
        obj.label = item.content
        arr.push(obj)
      })
      data.typeList = arr
    }
    // 点击图片出现的弹窗
    const showImage = (url) => {
      data.previewPictureSrc = url
      data.picturePreviewShow = true
      data.mockShow = true
    }
    // 获取问题分布数据
    const getQuestion = () => {
      const params = {
        key: data.taskSelected,
        questionCode: data.questionTypeSelected,
        status: data.stateSelected
      }

      getQuestionDistribution(params).then((res) => {
        if (res.code === 0) {
          // 获取并处理feature数据

          if (res.data) {
            const featureArr = []
            res.data.map((item) => {
              const newObj = {}
              newObj.geometry = {
                coordinates: [
                  parseFloat(item.longitude),
                  parseFloat(item.latitude)
                ],
                type: 'Point'
              }
              newObj.properties = item
              newObj.type = 'Feature'
              featureArr.push(newObj)
            })
            addCluster(featureArr)
          }
        }
      })
    }
    // 添加聚合图
    /**
     * params featureArr  每种聚合问题的geojson数据
     * params name   每种聚合问题的名称
     * params color  聚合的颜色
     */
    const addCluster = (featureArr) => {
      data.map.addSource('point-source', {
        type: 'geojson',
        data: {
          type: 'FeatureCollection',
          features: featureArr
        },
        cluster: true,
        clusterMaxZoom: 15,
        clusterRadius: 80
      })
      // 聚合图层
      data.map.addLayer({
        id: 'plantCluster',
        type: 'circle',
        source: 'point-source',
        filter: ['>=', 'point_count', 2],
        paint: {
          'circle-color': '#FF7500',
          'circle-radius': 24,
          'circle-stroke-color': 'rgba(155,85,26,0.5)',
          'circle-stroke-width': 5
        }
      })
      // 聚合数字
      data.map.addLayer({
        id: 'plantCluster-count',
        type: 'symbol',
        source: 'point-source',
        filter: ['has', 'point_count'],
        layout: {
          'text-field': '{point_count_abbreviated}',
          'text-size': 16,
          'text-ignore-placement': true,
          'text-allow-overlap': true
        },
        paint: {
          'text-color': '#fff',
          'text-opacity': 1
        }
      })
      // 具体点图层
      data.map.addLayer({
        id: 'plant-point',
        type: 'symbol',
        source: 'point-source',
        filter: ['!', ['has', 'point_count']],
        layout: {
          'icon-image': 'problem'
        }
      })
    }
    /**
     * 单击聚合图层出现的弹窗
     */
    const showClusterInfo = (e) => {
      // 移除点弹窗
      if (data.pointPoppupContent) {
        data.pointPoppupContent.remove()
      }
      const features = data.map.queryRenderedFeatures(e.point, {
        layers: ['plantCluster']
      })

      const clusterId = features[0].properties['cluster_id']

      const pointCount = features[0].properties['point_count']

      data.problemClusterId = clusterId

      data.problemPopupId = clusterId

      data.clusterPosition = features[0].geometry.coordinates
      data.map
        .getSource('point-source')
        .getClusterLeaves(clusterId, pointCount, 0, (err, fea) => {
          if (!err) {
            data.clusterList = []
            const typeList = []

            fea.map((item, index) => {
              const obj = {}
              obj.type = item.properties.questionName
              typeList.push(obj)
            })
            const typemap = new Map()
            typeList.forEach((i) => {
              const { type } = i
              if (typemap.has(type)) {
                let val = typemap.get(type)
                typemap.set(type, ++val)
              } else {
                typemap.set(type, 1)
              }
            })

            const typeObject = Object.fromEntries(typemap)

            for (var i in typeObject) {
              const obj = { type: '', number: 0 }

              obj.type = i
              obj.number = typeObject[i]
              data.clusterList.push(obj)
            }

            data.popup = new mapboxgl.Popup({
              closeButton: false
            })
              .setLngLat(data.clusterPosition)
              .setDOMContent(data.clusterPopup)
              .addTo(data.map)
          }
        })
      // 监听地图完成后

      data.map.on('zoom', foo)
    }
    /**
     * 单击具体问题点出现的弹窗
     */
    const showPlantPointInfo = (e) => {
      // 移除聚合弹窗
      if (data.popup) {
        data.popup.remove()
      }
      //  如果没有关闭聚合图层的zoom监听 就关闭zoom监听
      data.map.off('zoom', foo)
      var features = data.map.queryRenderedFeatures(e.point, {
        layers: ['plant-point']
      })
      // 当前所点击的点id
      data.pointId = features[0].properties.id
      data.position = [
        parseFloat(features[0].properties.longitude),
        parseFloat(features[0].properties.latitude)
      ]
      data.positionShow =
        parseFloat(features[0].properties.longitude).toFixed(6) +
        ',' +
        parseFloat(features[0].properties.latitude).toFixed(6)
      data.problemType = features[0].properties.questionName
      // 获取图片列表

      if (features[0].properties.fileImage) {
        data.hasImg = true
        var imgUrl = features[0].properties.fileImage
        var imgRes = imgUrl.split(',')
        data.imgList = imgRes
      } else {
        data.hasImg = false
        data.imgList = []
      }
      data.pointPoppupContent = new mapboxgl.Popup({
        closeButton: false
      })
        .setLngLat(data.position)
        .setDOMContent(data.pointPopup)
        .setMaxWidth('270px')
        .addTo(data.map)
      data.map.on('zoom', pointFoo)
    }
    const pointFoo = () => {
      // 当前所有点图层要素
      var relatedFeatures = data.map.querySourceFeatures('point-source', { sourceLayer: 'plant-point' })
      let change = true
      relatedFeatures.map((item) => {
        if (item.properties.id === data.pointId) {
          change = false
        }
      })
      if (change) {
        // 关闭监听
        data.map.off('zoom', pointFoo)
        // 移除点图层
        data.pointPoppupContent.remove()
      }
    }
    const foo = () => {
      // 当前所有集群要素
      const clusters = data.map.querySourceFeatures('point-source')

      let notChange = false
      for (let i = 0; i < clusters.length; i++) {
        if (clusters[i].id === data.problemClusterId) {
          notChange = true
          break
        }
      }
      // 如果聚合图的位置已经发生了改变并且popup没变的话,就移除popup
      if (!notChange) {
        data.map.off('zoom', foo)

        if (data.popup) {
          data.popup.remove()
          data.popup = null
        }
      }
    }
    // 查找问题类型
    const query = () => {
      // data.popup.remove()

      // 清空之前的所有图层
      if (data.map.getSource('point-source')) {
        if (data.map.getLayer('plantCluster')) {
          data.map.removeLayer('plantCluster')
          data.map.removeLayer('plantCluster-count')
        }
        if (data.map.getLayer('plant-point')) {
          data.map.removeLayer('plant-point')
        }
        data.map.removeSource('point-source')
      }
      // 移除聚合弹窗
      if (data.popup) {
        data.popup.remove()
      }
      // 移除点弹窗
      if (data.pointPoppupContent) {
        data.pointPoppupContent.remove()
      }
      getQuestion()
    }
    const queryEnter = () => {
      data.queryStyle = { backgroundColor: 'rgba(24, 144, 255, 0.8)' }
    }
    const queryLeave = () => {
      data.queryStyle = { backgroundColor: 'rgba(24, 144, 255, 1)' }
    }
    const resetEnter = () => {
      data.resetStyle = { border: '1px solid #1890FF' }
    }
    const resetLeave = () => {
      data.resetStyle = { border: '1px solid #acb9d1' }
    }
    // 重置
    const reset = () => {
      // 清空当前的所有图层和弹窗
      if (data.popup) {
        data.popup.remove()
        data.popup = null
      }
      if (data.pointPoppupContent) {
        data.pointPoppupContent.remove()
      }
      if (data.map.getSource('point-source')) {
        if (data.map.getLayer('plantCluster')) {
          data.map.removeLayer('plantCluster')
          data.map.removeLayer('plantCluster-count')
        }
        if (data.map.getLayer('plant-point')) {
          data.map.removeLayer('plant-point')
        }
        data.map.removeSource('point-source')
      }

      data.taskSelected = ''
      data.questionTypeSelected = ''
      data.stateSelected = 20

      getQuestion()
    }
    onMounted(() => {
      initMap()
      getQuestionType()
      getQuestion()
    })
    return {
      ...toRefs(data),
      initMap,
      query,
      reset,
      showImage,
      resetEnter,
      resetLeave,
      queryEnter,
      queryLeave
    }
  }
}
</script>
<style scoped lang='scss'>
.content {
  width: 100%;
  height: 100%;
  background-color: #eaeaea;
  box-sizing: border-box;
  padding: 0 15px 30px 15px;
  .title {
    width: 100%;
    height: 56px;
    margin-bottom: 5px;
    background-color: #fff;
    box-sizing: border-box;
    padding-left: 39px;
    font-size: 18px;
    font-family: Noto Sans SC-Medium, Noto Sans SC;
    font-weight: 500;
    color: #333333;
    line-height: 56px;
  }
  // 搜索栏
  .searchBar {
    width: 100%;
    height: 70px;
    background-color: #fff;
    box-sizing: border-box;
    padding-left: 43px;
    .searchItem {
      float: left;
      height: 100%;
      margin-right: 72px;
      display: flex;
      align-items: center;
      justify-content: center;

      input {
        height: 32px;
        height: 240px;
      }
      .n-select {
        width: 240px;
        // height: 32px;
        // border: 1px solid #acb9d1;
        border-radius: 4px;
      }
    }
    .btns {
      height: 100%;
      float: left;
      display: flex;
      align-items: center;
      button {
        width: 64px;
        height: 32px;
        border-radius: 2px;
      }
      .queryBtn {
        font-size: 14px;
        font-family: Noto Sans SC-Medium, Noto Sans SC;
        font-weight: 500;
        color: #ffffff;
        border: 0;
        border-radius: 3px;
        margin-right: 24px;
        cursor: pointer;
      }
      .resetBtn {
        background-color: #ffffff;
        border-radius: 3px;

        font-size: 14px;
        font-family: Noto Sans SC-Medium, Noto Sans SC;
        font-weight: 500;
        color: #1890ff;
        cursor: pointer;
      }
    }
  }
  // 地图
  .mapContent {
    width: 100%;
    box-sizing: border-box;
    overflow: hidden;
    // height: 847px;
    height: calc(100% - 100px);
    .map {
      width: 100%;
      height: 100%;
    }
    // 具体点弹窗
    .pointPopup {
      .item {
        position: relative;
        font-size: 14px;
        color: #fff;
        padding-left: 80px;

        .itemTitle {
          position: absolute;
          left: 0px;
          top: 0px;
          width: 80px;
          text-align: right;
        }
        .clusterNumber {
          width: 80px;
        }
        img {
          width: 67px;
          height: 37px;
          margin-right: 10px;
        }
      }
    }
    // 聚合弹窗
    .clusterPopup {
      .item {
        position: relative;
        font-size: 14px;
        color: #fff;

        padding-left: 90px;
        .itemtitle {
          position: absolute;
          left: 0px;
          top: 0px;
          width: 80px;
          text-align: right;
        }
        .clusterNumber {
          width: 80px;
        }

      }
    }
  }
}
.mock {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  justify-content: center;
  align-items: center;
}
:deep(.mapboxgl-popup-content) {
  background: #2d2d2d !important;
  font-size: 14px;
  font-family: Noto Sans SC-Regular, Noto Sans SC;
  font-weight: 400;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0) !important;
}
:deep(.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip) {
  border-top-color: #2d2d2d !important;
}
input::-webkit-input-placeholder {
  /* WebKit browsers，webkit内核浏览器 */
  color: rgba(194, 194, 194, 1);
}
input:-moz-placeholder {
  /* Mozilla Firefox 4 to 18 */
  color: rgba(194, 194, 194, 1);
}
input::-moz-placeholder {
  /* Mozilla Firefox 19+ */
  color: rgba(194, 194, 194, 1);
}
input:-ms-input-placeholder {
  /* Internet Explorer 10+ */
  color: rgba(194, 194, 194, 1);
}
</style>

